/*
 * @Author: lei
 * @Description: 
 * @FilePath: /code/template/function.h
 */
#include <cstddef>
#include <string>
#include <memory>

template<typename T>
T Add(T a, T b) {
	return a + b;
}

template<typename DstT, typename SrcT>
DstT Implicit_Cast(SrcT t) {
	return static_cast<DstT>(t);
}




template<typename T> 
class TypeToId {
public:
	static int const ID = -1;
	void copy(T* dst, T* src, size_t elem_count) {
		for(size_t i = 0; i < elem_count; ++i) {
			dst[i] = src[i];
		}
	}
};
//类模板和类模板的特化的作用，仅仅是指导编译器选择哪个编译
//但是特化之间、特化和它原型的类模板之间，是分别独立实现的。
template<> 
class TypeToId<int> {
public:
	static int const Id = 1;
	void copy(int* dst, int* src, size_t elem_count) {
		for(size_t i = 0; i < elem_count; ++i) {
			dst[i] = src[i];
		}
	}
};
template<> 
class TypeToId<double> {
public:
	static int const id = 2;
	void copy(double* dst, double* src, size_t elem_count) {
		for(size_t i = 0; i < elem_count; ++i) {
			dst[i] = src[i];
		}
	}
};
template<> 
class TypeToId<const char*> {
public:
	static int const ID = 3;
};
template<>
class TypeToId<std::string> {
public:
	static int const ID = 4;
	void copy(std::string& dst, std::string& src) {
		dst = src;
	}
	void move(std::string& dst, std::string& src) {
		dst = std::move(src);
	}
};



template <typename T, typename U> struct X            ;    // 0 
                                                           // 原型有两个类型参数
                                                           // 所以下面的这些偏特化的实参列表
                                                           // 也需要两个类型参数对应
template <typename T>             struct X<T,  T  > {};    // 1
template <typename T>             struct X<T*, T  > {};    // 2
template <typename T>             struct X<T,  T* > {};    // 3
template <typename U>             struct X<U,  int> {};    // 4
template <typename U>             struct X<U*, int> {};    // 5
template <typename U, typename T> struct X<U*, T* > {};    // 6
template <typename U, typename T> struct X<U,  T* > {};    // 7

template <typename T>             struct X<std::unique_ptr<T>, std::shared_ptr<T>>; // 8

X<float*,  int>      v0;                       
X<double*, int>      v1;                       
X<double,  double>   v2;                          
X<float*,  double*>  v3;                           
X<float*,  float*>   v4;                          
X<double,  float*>   v5;                          
X<int,     double*>  v6;                           
X<int*,    int>      v7;                       
X<double*, double>   v8;